<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 判断当前浏览器是否支持 IndexedDB
      window.indexedDB =
        window.indexedDB ||
        window.mozIndexedDB ||
        window.webkitIndexedDB ||
        window.msIndexedDB;

      if (!window.indexedDB) {
        alert("你的浏览器不支持IndexedDB");
      }

      /**
       * 打开数据库
       * window.indexedDB.open(name, version)
       * name: 数据库名称。如果指定的数据库不存在，就会新建数据库。
       * version: 指定数据库版本（整数）。如果省略，打开已有数据库时，默认为当前版本；
       * 新建数据库时，默认为 1。当你想要更改数据库格式（比如增加对象存储，非增加记录），必须指定更高版本。
       * 返回值：IDBOpenDBRequest 对象，这个对象通过三种事件 error、success、upgradeneeded，处理打开数据库的操作结果。
       */
      const request = window.indexedDB.open("myIndexedDB", 1);

      // success 事件表示成功打开数据库
      // request.onsuccess = (event) => {
      //   db = event.target.result;
      //   console.log("打开 IndexedDB 成功");
      // };
      // error 事件表示打开数据库失败
      // request.onerror = (event) => {
      //   console.log("打开 IndexedDB 失败");
      // };
      // 如果指定的版本号，大于数据库的实际版本号，就会发生数据库升级事件 upgradeneeded
      // request.onupgradeneeded = function (event) {
      //   console.log("当前数据库版本号为" + event.newVersion);
      // };

      /**
       * 打开数据库返回的 IDBOpenDBRequest 对象，可以使用该对象 close() 方法来关闭数据库
       */
      let db;
      request.onsuccess = (event) => {
        // console.log("打开 IndexedDB1 成功");
        db = request.result;
        //   db.close();
        // console.log("关闭数据库成功");
        // add();
        // read();
        // readAll();
        // update();
        // remove();
      };

      // request.onerror = (event) => {
      //   console.error("Database error: ", event.target.error);
      // };

      /**
       * 删除数据库
       * indexedDB.deleteDatabase（name） 删除指定名称的数据库
       */
      // window.indexedDB.deleteDatabase("myIndexedDB");

      /**
       * 新建对象仓库（表）
       * 建完数据库后，我们需要一张表来存储信息，使用到的是 IDBDatabase.createObjectStore()
       * const objectStore = IDBDatabase.createObjectStore(name, options)
       * name：被创建的 object store 的名称
       * options：keyPath：存储使用的主键;autoIncrement：是否使用自动递增的整数作为主键，默认为 false
       * 该方法创建并返回一个新的 object store 或 index
       */
      // request.onupgradeneeded = function (event) {
      //   db = event.target.result;
      //   const objectStore = db.createObjectStore("person", { keyPath: "id" });
      // };

      // 优化
      request.onupgradeneeded = function (event) {
        db = event.target.result;
        var objectStore;
        if (!db.objectStoreNames.contains("person")) {
          objectStore = db.createObjectStore("person", { keyPath: "id" });
        }
      };

      /**
       * 主键（key）是默认建立索引的属性
       * 比如，数据记录是{ id: 1, name: '张三' }，那么id属性可以作为主键
       * 主键也可以指定为下一层对象的属性，比如{ foo: { bar: 'baz' } }的foo.bar也可以指定为主键
       * 如果数据记录里面没有合适作为主键的属性，那么可以让 IndexedDB 自动生成主键
       * 下面代码中，指定主键为一个递增的整数
       */
      // var objectStore = db.createObjectStore("person", { autoIncrement: true });

      /**
       * 新建对象仓库以后，下一步可以新建索引
       * 下面代码中，IDBObject.createIndex()的三个参数分别为索引名称、索引所在的属性、配置对象（说明该属性是否包含重复的值）
       */
      // request.onupgradeneeded = function (event) {
      //   db = event.target.result;
      //   var objectStore = db.createObjectStore("person", { keyPath: "id" });
      //   objectStore.createIndex("name", "name", { unique: false });
      //   objectStore.createIndex("email", "email", { unique: true });
      // };

      /**
       * 新增数据
       * 新增数据指的是向对象仓库写入数据记录，这需要通过事务完成
       * 写入数据需要新建一个事务，新建时必须指定表格名称和操作模式（"只读"或"读写"）
       * 新建事务以后，通过IDBTransaction.objectStore(name)方法，拿到 IDBObjectStore 对象，再通过表格对象的add()方法，向表格写入一条记录
       * 写入操作是一个异步操作，通过监听连接对象的success事件和error事件，了解是否写入成功
       */
      function add() {
        console.log("db", db);
        var request = db
          .transaction(["person"], "readwrite")
          .objectStore("person")
          .add({ id: 1, name: "张三", age: 24, email: "zhangsan@example.com" });

        request.onsuccess = function (event) {
          console.log("数据写入成功");
        };

        request.onerror = function (event) {
          console.log("数据写入失败");
        };
      }

      /**
       * 读取数据
       * 读取数据也是通过事务完成，objectStore.get()方法用于读取数据，参数是主键的值
       */
      function read() {
        var transaction = db.transaction(["person"]);
        var objectStore = transaction.objectStore("person");
        var request = objectStore.get(1);

        request.onerror = function (event) {
          console.log("事务失败");
        };

        request.onsuccess = function (event) {
          if (request.result) {
            console.log("Name: " + request.result.name);
            console.log("Age: " + request.result.age);
            console.log("Email: " + request.result.email);
          } else {
            console.log("未获得数据记录");
          }
        };
      }

      /**
       * 遍历数据
       * 遍历数据表格的所有记录，要使用指针对象 IDBCursor，新建指针对象的openCursor()方法是一个异步操作，所以要监听success事件
       */
      function readAll() {
        var objectStore = db.transaction("person").objectStore("person");

        objectStore.openCursor().onsuccess = function (event) {
          var cursor = event.target.result;

          if (cursor) {
            console.log("Id: " + cursor.key);
            console.log("Name: " + cursor.value.name);
            console.log("Age: " + cursor.value.age);
            console.log("Email: " + cursor.value.email);
            cursor.continue();
          } else {
            console.log("没有更多数据了！");
          }
        };
      }

      /**
       * 更新数据
       * 更新数据要使用IDBObject.put()方法，put()方法自动更新了主键为1的记录
       */
      function update() {
        var request = db
          .transaction(["person"], "readwrite")
          .objectStore("person")
          .put({ id: 1, name: "李四", age: 35, email: "lisi@example.com" });

        request.onsuccess = function (event) {
          console.log("数据更新成功");
        };

        request.onerror = function (event) {
          console.log("数据更新失败");
        };
      }

      /**
       * 删除数据
       * IDBObjectStore.delete()方法用于删除记录
       */
      function remove() {
        var request = db
          .transaction(["person"], "readwrite")
          .objectStore("person")
          .delete(1);

        request.onsuccess = function (event) {
          console.log("数据删除成功");
        };
      }

      /**
       * 使用索引
       * 索引的意义在于，可以让你搜索任意字段，也就是说从任意字段拿到数据记录
       * 如果不建立索引，默认只能搜索主键（即从主键取值）
       * 假定新建表格的时候，对name字段建立了索引，就可以从name找到对应的数据记录了
       */

      // let request1 = window.indexedDB.open("myIndexedDB", 2);

      // let db1;
      // request1.onsuccess = function (event) {
      //   db1 = request1.result;
      //   // console.log("success");
      //   read1();
      // };

      // request1.onupgradeneeded = function (event) {
      //   db1 = event.target.result;
      //   let objectStore = db1.createObjectStore("myObjectStore", {
      //     keyPath: "id",
      //   });
      //   objectStore.createIndex("name", "name", { unique: false });
      //   // 注意：不要在这里启动其他事务
      // };

      // function read1() {
      //   let transaction = db1.transaction(["myObjectStore"], "readonly");
      //   let store = transaction.objectStore("myObjectStore");
      //   let index = store.index("name");
      //   let request11 = index.get("李四");
      //   if (request11.result) {
      //     console.log("Name: " + request11.result.name);
      //   } else {
      //     console.log("未获得数据记录");
      //   }
      // }

      // 打开数据库
      // const request = window.indexedDB.open("myIndexedDB", 1);
      // let db;

      // // 成功打开数据库时的处理
      // request.onsuccess = (event) => {
      //   db = request.result;
      //   console.log("Database opened successfully.");

      //   // 检查是否需要添加新的对象存储
      //   if (!db.objectStoreNames.contains("test")) {
      //     // 关闭现有数据库连接
      //     db.close();

      //     // 重新打开数据库，触发版本升级
      //     const newVersionRequest = window.indexedDB.open(
      //       "myIndexedDB",
      //       db.version + 1
      //     );

      //     newVersionRequest.onupgradeneeded = (event) => {
      //       db = event.target.result;
      //       // 创建新的对象存储
      //       if (!db.objectStoreNames.contains("test")) {
      //         const objectStore = db.createObjectStore("test", {
      //           keyPath: "id",
      //         });
      //         console.log("Object store 'test' created successfully.");
      //       }
      //     };

      //     newVersionRequest.onsuccess = (event) => {
      //       db = newVersionRequest.result;
      //       console.log("Database version upgraded and opened successfully.");
      //     };

      //     newVersionRequest.onerror = (event) => {
      //       console.error("Error opening database:", event.target.errorCode);
      //     };
      //   }
      // };

      // // 初始数据库升级处理
      // request.onupgradeneeded = function (event) {
      //   db = event.target.result;
      //   if (!db.objectStoreNames.contains("person")) {
      //     db.createObjectStore("person", { keyPath: "id" });
      //     console.log("Object store 'person' created successfully.");
      //   }
      // };

      // request.onerror = (event) => {
      //   console.error("Error opening database:", event.target.errorCode);
      // };
    </script>
  </body>
</html>
